#Boa:Frame:fServer

import wx
import sys, os
import threading
import subprocess
import time,platform
from StringIO import StringIO

if platform.system()[0]!="W":
    Win=False
else:
    Win=True

noenter = lambda s:s.replace('\r','').replace('\n','').replace(' ','')
        
class tryget(threading.Thread):
    def __init__(self, caller):
        threading.Thread.__init__(self)
        self.caller = caller
        self.si=""
        self.t=1
        self.flag=False
        
    def run(self):
        while not self.flag:
            try:
                if self.t==1:
                    delta=self.caller.p.stdout.read(1)
                else:
                    delta=self.caller.p.stderr.read(1)
                self.si+=delta
                if delta=='':
                    self.flag=True
                else:
                    self.caller.upmsg(self.t,delta)
            except:
                #self.flag=True
                #break
                pass

class TETunnel(threading.Thread):
    def __init__(self, caller):
        threading.Thread.__init__(self)
        self.caller = caller
         
    def run(self):
            #try:
            port=noenter(self.caller.tcPort.GetValue())
            phost=noenter(self.caller.tcPHost.GetValue())
            pport=noenter(self.caller.tcPPort.GetValue())
            bhost=noenter(self.caller.tcBHost.GetValue())
            bw=noenter(self.caller.tcBw.GetValue())
            arg=["encryptedtunnel","-s","-l",port,"-i",phost,"-p",pport,"-w",bw]
            if bhost!="":
                arg+=["-b",bhost]
            if Win:
                startupinfo = subprocess.STARTUPINFO()
                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
                startupinfo.wShowWindow = subprocess.SW_HIDE
                self.p = subprocess.Popen(args=arg,bufsize=0,stdout=subprocess.PIPE,stderr=subprocess.PIPE,startupinfo=startupinfo)
            else:
                self.p = subprocess.Popen(args=arg,bufsize=0,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            self.t = tryget(self) 
            self.t.setDaemon(True)
            self.t.start()
            self.t2 = tryget(self)
            self.t2.t=0
            self.t2.setDaemon(True)
            self.t2.start()
            #fcntl.fcntl(self.p.stdout, fcntl.F_SETFL, os.O_NONBLOCK)
            #fcntl.fcntl(self.p.stderr, fcntl.F_SETFL, os.O_NONBLOCK)
            a=""
            while a=="" and self.p.poll()==None:
                try:
                    while len(self.t.si)<150 and self.p.poll()==None:
                        time.sleep(0.05)
                    a=self.t.si
                except:
                    pass
                time.sleep(0.05)
            #wx.CallAfter(self.caller.UpdateETDebug,a)
            if self.p.poll()==None:
                key = a.split('\n')[1][5:]
                wx.CallAfter(self.caller.SetKey,key)
            #else:
            #    s=self.p.stdout.read()
            #    wx.CallAfter(self.caller.UpdateETDebug,s)
            #    s=self.p.stderr.read()
            #    wx.CallAfter(self.caller.UpdateETErr,s)
            #except:
            #pass
            #except:
            #pass
            #try:
            #s=self.p.communicate()
            #wx.CallAfter(self.caller.UpdateETDebug,s[0])
            #wx.CallAfter(self.caller.UpdateETErr,s[1])
            #wx.CallAfter(self.caller.UpdateETDebug,self.ta.si[0])
            #wx.CallAfter(self.caller.UpdateETErr,self.ta.si[0])
            #except: 
            self.p.wait()
            wx.CallAfter(self.caller.OnETStopped)
            
    def upmsg(self, t, text):
            if text=='\r':
                return
            if t==1:
                wx.CallAfter(self.caller.UpdateETDebug,text)
            else:
                wx.CallAfter(self.caller.UpdateETErr,text)

class TPolipo(threading.Thread):
    def __init__(self, caller):
        threading.Thread.__init__(self)
        self.caller = caller
        
    def run(self):
            #try:
            phost=noenter(self.caller.tcPHost.GetValue())
            pport=noenter(self.caller.tcPPort.GetValue())
            if Win:
                null="NUL"
            else:
                null="/dev/null"
            arg=["polipo","-c",null,"proxyAddress="+phost,"proxyPort="+pport]
            if Win:
                startupinfo = subprocess.STARTUPINFO()
                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
                startupinfo.wShowWindow = subprocess.SW_HIDE
                self.p = subprocess.Popen(args=arg,bufsize=0,stdout=subprocess.PIPE,stderr=subprocess.PIPE,startupinfo=startupinfo)
            else:
                self.p = subprocess.Popen(args=arg,bufsize=0,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            self.t = tryget(self) 
            self.t.setDaemon(True)
            self.t.start()
            self.t2 = tryget(self)
            self.t2.t=0
            self.t2.setDaemon(True)
            self.t2.start()
            self.p.wait()
            wx.CallAfter(self.caller.OnPStopped)
            
    def upmsg(self, t, text):
            if text=='\r':
                return
            if t==1:
                wx.CallAfter(self.caller.UpdatePDebug,text)
            else:
                wx.CallAfter(self.caller.UpdatePErr,text)

def create(parent):
    return fServer(parent)

[wxID_FSERVER, wxID_FSERVERBSUBMIT, wxID_FSERVERBUTTON1, 
 wxID_FSERVERSBADVANCE, wxID_FSERVERSBET, wxID_FSERVERSBPOLIPO, 
 wxID_FSERVERSBSTATUS, wxID_FSERVERSTATICTEXT1, wxID_FSERVERSTATICTEXT2, 
 wxID_FSERVERSTATICTEXT3, wxID_FSERVERSTATICTEXT4, wxID_FSERVERSTATICTEXT5, 
 wxID_FSERVERSTATICTEXT6, wxID_FSERVERSTET, wxID_FSERVERSTKEY, 
 wxID_FSERVERSTPOLIPO, wxID_FSERVERSTPORT, wxID_FSERVERTCBHOST, 
 wxID_FSERVERTCBW, wxID_FSERVERTCET, wxID_FSERVERTCETERR, wxID_FSERVERTCKEY, 
 wxID_FSERVERTCPHOST, wxID_FSERVERTCPOLIPO, wxID_FSERVERTCPOLIPOERR, 
 wxID_FSERVERTCPORT, wxID_FSERVERTCPPORT, 
] = [wx.NewId() for _init_ctrls in range(27)]

class fServer(wx.Frame):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FSERVER, name=u'fServer', parent=prnt,
              pos=wx.Point(359, 114), size=wx.Size(628, 601),
              style=wx.DEFAULT_FRAME_STYLE, title=u'Server')
        self.SetClientSize(wx.Size(272, 410))

        self.stPort = wx.StaticText(id=wxID_FSERVERSTPORT, label=u'Port:',
              name=u'stPort', parent=self, pos=wx.Point(8, 16), size=wx.Size(30,
              17), style=0)

        self.tcPort = wx.TextCtrl(id=wxID_FSERVERTCPORT, name=u'tcPort',
              parent=self, pos=wx.Point(104, 16), size=wx.Size(80, 27), style=0,
              value=u'32123')

        self.stKey = wx.StaticText(id=wxID_FSERVERSTKEY, label=u'Secret Key:',
              name=u'stKey', parent=self, pos=wx.Point(8, 56), size=wx.Size(66,
              17), style=0)

        self.tcKey = wx.TextCtrl(id=wxID_FSERVERTCKEY, name=u'tcKey',
              parent=self, pos=wx.Point(104, 56), size=wx.Size(160, 160),
              style=wx.TE_MULTILINE, value=u'')

        self.sbStatus = wx.StaticBox(id=wxID_FSERVERSBSTATUS, label=u'Status',
              name=u'sbStatus', parent=self, pos=wx.Point(8, 224),
              size=wx.Size(256, 120), style=0)

        self.staticText1 = wx.StaticText(id=wxID_FSERVERSTATICTEXT1,
              label=u'encrypedtunnel:', name='staticText1', parent=self,
              pos=wx.Point(24, 264), size=wx.Size(99, 17), style=0)

        self.staticText2 = wx.StaticText(id=wxID_FSERVERSTATICTEXT2,
              label=u'polipo:', name='staticText2', parent=self,
              pos=wx.Point(24, 296), size=wx.Size(42, 17), style=0)

        self.stET = wx.StaticText(id=wxID_FSERVERSTET, label=u'Stopped',
              name=u'stET', parent=self, pos=wx.Point(184, 264),
              size=wx.Size(51, 17), style=0)

        self.stPolipo = wx.StaticText(id=wxID_FSERVERSTPOLIPO, label=u'Stopped',
              name=u'stPolipo', parent=self, pos=wx.Point(184, 296),
              size=wx.Size(51, 17), style=0)

        self.bSubmit = wx.Button(id=wxID_FSERVERBSUBMIT, label=u'Launch',
              name=u'bSubmit', parent=self, pos=wx.Point(24, 360),
              size=wx.Size(101, 40), style=0)
        self.bSubmit.Bind(wx.EVT_BUTTON, self.OnSubmit, id=wxID_FSERVERBSUBMIT)

        self.button1 = wx.Button(id=wxID_FSERVERBUTTON1, label=u'Advanced >>>',
              name='button1', parent=self, pos=wx.Point(144, 360),
              size=wx.Size(104, 40), style=0)
        self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button,
              id=wxID_FSERVERBUTTON1)

        self.sbAdvance = wx.StaticBox(id=wxID_FSERVERSBADVANCE,
              label=u'Advanced Settings', name=u'sbAdvance', parent=self,
              pos=wx.Point(8, 416), size=wx.Size(256, 176), style=0)

        self.staticText3 = wx.StaticText(id=wxID_FSERVERSTATICTEXT3,
              label=u'PolipoPort:', name='staticText3', parent=self,
              pos=wx.Point(32, 448), size=wx.Size(68, 17), style=0)

        self.staticText4 = wx.StaticText(id=wxID_FSERVERSTATICTEXT4,
              label=u'PolipoHost:', name='staticText4', parent=self,
              pos=wx.Point(32, 480), size=wx.Size(70, 17), style=0)

        self.staticText5 = wx.StaticText(id=wxID_FSERVERSTATICTEXT5,
              label=u'Bind Host:', name='staticText5', parent=self,
              pos=wx.Point(32, 512), size=wx.Size(62, 17), style=0)

        self.staticText6 = wx.StaticText(id=wxID_FSERVERSTATICTEXT6,
              label=u'Bandwidth:', name='staticText6', parent=self,
              pos=wx.Point(32, 544), size=wx.Size(69, 17), style=0)

        self.tcPPort = wx.TextCtrl(id=wxID_FSERVERTCPPORT, name=u'tcPPort',
              parent=self, pos=wx.Point(152, 448), size=wx.Size(80, 27),
              style=0, value=u'18123')

        self.tcPHost = wx.TextCtrl(id=wxID_FSERVERTCPHOST, name=u'tcPHost',
              parent=self, pos=wx.Point(152, 480), size=wx.Size(80, 27),
              style=0, value=u'127.0.0.1')

        self.tcBHost = wx.TextCtrl(id=wxID_FSERVERTCBHOST, name=u'tcBHost',
              parent=self, pos=wx.Point(152, 512), size=wx.Size(80, 27),
              style=0, value=u'')

        self.tcBw = wx.TextCtrl(id=wxID_FSERVERTCBW, name=u'tcBw', parent=self,
              pos=wx.Point(152, 544), size=wx.Size(80, 27), style=0,
              value=u'102400')

        self.sbPolipo = wx.StaticBox(id=wxID_FSERVERSBPOLIPO,
              label=u'Polipo Debugging Infomation', name=u'sbPolipo',
              parent=self, pos=wx.Point(288, 16), size=wx.Size(328, 272),
              style=0)

        self.tcPolipo = wx.TextCtrl(id=wxID_FSERVERTCPOLIPO, name=u'tcPolipo',
              parent=self, pos=wx.Point(304, 48), size=wx.Size(296, 104),
              style=wx.TE_MULTILINE, value=u'')

        self.tcPolipoErr = wx.TextCtrl(id=wxID_FSERVERTCPOLIPOERR,
              name=u'tcPolipoErr', parent=self, pos=wx.Point(304, 160),
              size=wx.Size(296, 112), style=wx.TE_MULTILINE, value=u'')

        self.sbET = wx.StaticBox(id=wxID_FSERVERSBET,
              label=u'encryptedtunnel Debugging Infomation', name=u'sbET',
              parent=self, pos=wx.Point(288, 296), size=wx.Size(328, 296),
              style=0)

        self.tcET = wx.TextCtrl(id=wxID_FSERVERTCET, name=u'tcET', parent=self,
              pos=wx.Point(304, 320), size=wx.Size(296, 128),
              style=wx.TE_MULTILINE, value=u'')

        self.tcETErr = wx.TextCtrl(id=wxID_FSERVERTCETERR, name=u'tcETErr',
              parent=self, pos=wx.Point(304, 456), size=wx.Size(296, 120),
              style=wx.TE_MULTILINE, value=u'')

    def __init__(self, parent):
        self._init_ctrls(parent)
        
    def OnButton1Button(self, event):
        if self.button1.GetLabel()[0]=="A":
            self.SetClientSize(wx.Size(628, 601))
            self.button1.SetLabel("<<< Simple")
        else:
            self.SetClientSize(wx.Size(272, 410))
            self.button1.SetLabel("Advanced >>>")
    
    def OnSubmit(self, event):
        if self.bSubmit.GetLabel()[0]=="L":
            self.tcET.Clear()
            self.tcETErr.Clear()
            self.tcPolipo.Clear()
            self.tcPolipoErr.Clear()
            self.t = TETunnel(self)
            self.t.setDaemon(True)
            self.t.start()
            self.stET.SetLabel("Running")
            self.t2 = TPolipo(self)
            self.t2.setDaemon(True)
            self.t2.start()
            self.stPolipo.SetLabel("Running")
            self.bSubmit.SetLabel("Stop")
        else:
            if not self.t2.p.poll():
                self.OnPStopping()
                self.t2.p.kill()
            if not self.t.p.poll():
                self.OnETStopping()
                self.t.p.kill()
    
    def OnPStopping(self):
        self.stPolipo.SetLabel("Exiting")
    
    def OnPStopped(self):
        self.stPolipo.SetLabel("Stopped")
        if self.stET.GetLabel()[6]=="d":
            self.bSubmit.SetLabel("Launch")
        
    def OnETStopping(self):
        self.stET.SetLabel("Exiting")
    
    def OnETStopped(self):
        self.stET.SetLabel("Stopped")
        if self.stPolipo.GetLabel()[6]=="d":
            self.bSubmit.SetLabel("Launch")
    
    def UpdateETDebug(self, text):
        if not self.isset('self.po'):
            self.po=""
        try:
            self.tcET.AppendText(self.po+text)
            self.po=""
        except:
            self.po+=text
    
    def UpdateETErr(self, text):
        if not self.isset('self.po2'):
            self.po2=""
        try:
            self.tcETErr.AppendText(self.po2+text)
            self.po2=""
        except:
            self.po2+=text
        
    def UpdatePDebug(self, text):
        if not self.isset('self.po3'):
            self.po3=""
        try:
            self.tcPolipo.AppendText(self.po3+text)
            self.po3=""
        except:
            self.po3+=text
    
    def UpdatePErr(self, text):
        if not self.isset('self.po4'):
            self.po4=""
        try:
            self.tcPolipoErr.AppendText(self.po4+text)
            self.po4=""
        except:
            self.po4+=text
    
    def SetKey(self, key):
        self.tcKey.SetValue(key)
        
    def isset(self, v):  
        try:  
            type (eval(v))  
        except:  
            return 0  
        else:  
            return 1

class BoaApp1(wx.App):
    def OnInit(self):
        self.main = create(None)
        self.main.Show()
        self.SetTopWindow(self.main)
        return True

def main():
    application = BoaApp1(0)
    application.MainLoop()

if __name__ == '__main__':
    main()
